W3e = {}
local mt = {}
W3e.__index = mt
setmetatable(W3e, mt)



function W3e.new(path)
	local self = setmetatable({}, W3e)
	local file = io.open( path, 'rb' )
	self.file_string = file:read '*a'
	file:close()
	return self
end

function mt:load()
	--------------解析头部标志------------------
	local binary_reader = Binary_reader.new(self.file_string)

	--读4个字节固定长度的字符串
	local flag = binary_reader:read 'c4'
	if flag ~= 'W3E!' then
		log.error('解析w3e文件：该文件格式错误')
		return nil
	end

	self.version = binary_reader:read 'l'

	--	地形贴图类型集合
	self.tileset = binary_reader:read 'b'
	--	没懂什么意思
	self.custom_tileset = binary_reader:read 'l'

	-- print('tileset:', self.tileset, self.custom_tileset)

	--	地面贴图
	self.tileset_texture_count = binary_reader:read 'l'
	self.tileset_ids = {}
	for i = 1, self.tileset_texture_count do
		self.tileset_ids[i] = binary_reader:read 'c4'
	end

	--	悬崖贴图
	self.cliffset_texture_count = binary_reader:read 'l'
	self.cliffset_ids = {}
	for i = 1, self.cliffset_texture_count do
		self.cliffset_ids[i] = binary_reader:read 'c4'
	end
	
	--	格子数+1
	self.width = binary_reader:read 'l'
	self.height = binary_reader:read 'l'

	--	左下角的点位置
	self.offset = {
		--	x, y
		binary_reader:read 'f',
		binary_reader:read 'f',
	}
	--	以32*32正方形地形为例，中心为(0,0)
	--	width = height = 33 = 32+1
	--	offset[1] = offset[2] = -2048 = -16*128
	

	--	起始位置为左下角
	self.corners = {}
	for j = 1, self.height do
		for i = 1, self.width do
			local corner = {}
			if not self.corners[i] then
				self.corners[i] = {}
			end
			--	先宽后高
			self.corners[i][j] = corner
			
			corner.height = ((binary_reader:read 'h')-8192)/512

			local water_and_edge = binary_reader:read 'h'
			corner.water_height = ((water_and_edge & 0x3FFF) - 8192) / 512
			corner.map_edge = water_and_edge & 0x4000

			local texture_and_flags = binary_reader:read 'b'
			corner.ground_texture = texture_and_flags & 0x0f
			corner.textture_type = self.tileset_ids[corner.ground_texture+1]

			corner.ramp = texture_and_flags & 0x10
			corner.blight = texture_and_flags & 0x20
			corner.water = texture_and_flags & 0x40
			corner.boundary = texture_and_flags & 0x80

			local variation = binary_reader:read 'b'
			corner.ground_variation = variation & 0x1f
			corner.cliff_variation = (variation & 0xe0) >> 5

			local misc = binary_reader:read 'b'
			corner.cliff_texture = (misc & 0xf0) >> 4
			corner.layer_height = misc & 0x0f

			-- print(corner.cliff_texture, corner.layer_height)
		end
	end

	-- for width = 1, 5 do
	-- 	for height = 1, 5 do
	-- 		local corner = self.corners[width][height]
	-- 		local tips = {}
	-- 		for k, v in pairs(corner) do
	-- 			tips[#tips+1] = {
	-- 				key = k,
	-- 				val = v,
	-- 			}
	-- 		end
	-- 		table.sort(tips, function (sec, fir)
	-- 			return sec.key < fir.key
	-- 		end)
	-- 		print('---------------------', width, height)
	-- 		for _, v in ipairs(tips) do
	-- 			print(v.key, v.val)
	-- 		end
	-- 	end
	-- end

end

--	参数为具体的范围数值
function mt:write_terrain2(_minx, _miny, _maxx, _maxy)
	local minx, miny, maxx, maxy
	if not _minx or not _miny then
		minx = 1
		miny = 1
	else
		if _minx < self.offset[1] then
			_minx = self.offset[1]
			log.warn('强制修正左下角的X坐标')
		end
		minx = math.floor((_minx - self.offset[1])/128)+1

		if _miny < self.offset[2] then
			_miny = self.offset[2]
			log.warn('强制修正左下角的Y坐标')
		end
		miny = math.floor((_miny - self.offset[2])/128)+1
	end
	if not _maxx or not _maxy then
		maxx = self.width
		maxy = self.height
	else
		local x = self.offset[1] + 128*(self.width-1)
		if _maxx > x then
			_maxx = x
			log.warn('强制修正右上角的X坐标')
		end
		maxx = math.ceil((_maxx - x)/128) + self.width

		local y = self.offset[2] + 128*(self.height-1)
		if _maxy > y then
			_maxy = y
			log.warn('强制修正右上角的Y坐标')
		end
		maxy = math.ceil((_maxy - y)/128) + self.height
	end

	local x = self.offset[1]
	local y = self.offset[2]
	local types = {}
	local h = 0
	local w = 0
	for height = miny, maxy do
		h = h +1
		w = 0
		for width = minx, maxx do
			w = w + 1
			if not types[w] then
				types[w] = {}
			end
			types[w][h] = {
				x = x + (width-1) * 128,
				y = y + (height-1) * 128,
				type = self.corners[width][height].textture_type,
			}
		end
	end

	return types
end

function mt:save()
	local binary_writer = Binary_writer.new()

	binary_writer:write('c4', 'W3E!')
	binary_writer:write('l', self.version)
	binary_writer:write('b', self.tileset)
	binary_writer:write('l', self.custom_tileset)
	
	binary_writer:write('l', self.tileset_texture_count)
	for i = 1, self.tileset_texture_count do
		binary_writer:write('c4', self.tileset_ids[i])
	end
	
	binary_writer:write('l', self.cliffset_texture_count)
	for i = 1, self.cliffset_texture_count do
		binary_writer:write('c4', self.cliffset_ids[i])
	end

	binary_writer:write('l', self.width)
	binary_writer:write('l', self.height)
	binary_writer:write('f', self.offset[1])
	binary_writer:write('f', self.offset[2])

	for j = 1, self.height do
		for i = 1, self.width do
			local corner = self.corners[i][j]
			binary_writer:write('h', corner.height*512+8192)
			binary_writer:write('h', corner.water_height*512+8192 + corner.map_edge)
			binary_writer:write('B', corner.ground_texture+corner.ramp+corner.blight+corner.water+corner.boundary)			
			binary_writer:write('B', corner.ground_variation+ (corner.cliff_variation<<5) )
			binary_writer:write('B', corner.layer_height+ (corner.cliff_texture<<4) )
		end
	end

	return binary_writer:file_write()
end
